package com.example.frameboot.common;

import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


/**
 * @author limeng8
 * @ClassName: DateUtils
 * @Description: 日期处理公共类
 * @date 2020年1月16日 下午20:55:19
 */
@Slf4j
public class DateUtils {


    // 私有构造方法，禁止创建对象
    private DateUtils() {
    }

    /**
     * @param date
     * @return
     * @Description: 日期格式化
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date getNowDateShort(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = formatter.format(date);
        ParsePosition pos = new ParsePosition(8);
        Date currentTime_2 = formatter.parse(dateString, pos);
        return currentTime_2;
    }

    /**
     * @param date
     * @return
     * @Description: 日期增加一天
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date dateReFormat(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE) + 1);
        return calendar.getTime();
    }

    /**
     * @param date
     * @param increaseNum 增加日期
     * @return
     * @Description: 日期增加指定数量
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date dateIncrease(Date date, int increaseNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE) + increaseNum);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()));
        } catch (ParseException e) {
            log.error("日期转换失败", e);
        }

        return retDate;
    }

    /****
     * 传入具体日期 ，返回具体日期减少一天
     * @param Date 日期(2017-04-13)
     * @param date
     * @return 2017-04-12
     * @throws ParseException
     */
    public static Date subDay(Date dt, int subNum) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.DAY_OF_MONTH, subNum);
        Date dt1 = rightNow.getTime();
        //String reStr = sdf.format(dt1);
        return dt1;
    }

    /**
     * @param date
     * @param increaseNum 增加月数
     * @return
     * @Description: 日期增加月数
     * @author changjb
     * @date 2020年5月11日 上午10:05:19
     */
    public static Date dateIncreaseMonth(Date date, int increaseNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + increaseNum, calendar.get(Calendar.DATE));

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()));
        } catch (ParseException e) {
            log.error("日期转换失败", e);
        }

        return retDate;
    }

    /**
     * @param date
     * @param increaseNum 增加年数
     * @return
     * @Description: 日期增加年数
     * @author limeng8
     * @date 2020年7月7日 上午15:53:19
     */
    public static Date dateIncreaseYear(Date date, int increaseNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR) + increaseNum, calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE));

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()));
        } catch (ParseException e) {
            log.error("日期转换失败", e);
        }

        return retDate;
    }

    /**
     * @param date        源日期
     * @param decreaseNum 减少天数
     * @return
     * @Description: 日期减除函数
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date dateDecrease(Date date, int decreaseNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE) - decreaseNum);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()));
        } catch (ParseException e) {
            log.error("日期转换失败", e);
        }

        return retDate;
    }

    /**
     * @param date
     * @return
     * @throws ParseException
     * @Description: 清零日期对象的时分秒
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date zeroToDetailTime(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            date = dateFormat.parse(dateFormat.format(date));
        } catch (ParseException e) {
            log.error("日期转换失败", e);
        }
        return date;
    }

    /**
     * @param date    基本日期
     * @param hour    增加小时
     * @param miniute 增加分钟
     * @param second  增加秒
     * @return
     * @Description: 增加日期的时分秒
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date timeIncrease(Date date, int hour, int miniute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE),
                calendar.get(Calendar.HOUR_OF_DAY) + hour, calendar.get(Calendar.MINUTE) + miniute,
                calendar.get(Calendar.SECOND) + second);
        return calendar.getTime();
    }

    /**
     * @param dateStr
     * @return
     * @Description: 将日期字符串转换成日期
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date parseDateMonthTime(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return date;
    }

    /**
     * @param dateStr
     * @return
     * @Description: 将日期字符串转换成日期
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date parseDateTime(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        if (date == null) {
            SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            try {
                date = dateFormat2.parse(dateStr);
            } catch (ParseException e) {
                log.error("日期转换异常", e);
            }
        }
        return date;
    }

    /**
     * @param dateStr
     * @return
     * @Description: 将日期字符串转换成日期（不带秒）
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date parseDateTimeNoSecond(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return date;
    }

    /**
     * @param dateStr
     * @return
     * @throws ParseException
     * @Description: 将日期字符串转换成日期
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date parseDate(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return date;
    }

    /**
     * @param date
     * @return
     * @Description: 将日期转换成日期字符串（含时分秒）
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static String formatDateTime(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return dateFormat.format(date);
    }

    /**
     * @param date
     * @return
     * @Description:将日期转换成日期字符串（不含时分秒）
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static String formatDate(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(date);
    }

    /**
     * @param date
     * @return
     * @Description: 转换成简写日期格式
     * @author limeng8
     * @date 2020年1月16日 下午20:55:19
     */
    public static String formatSimpleDate(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(date);
    }

    /**
     * @param date
     * @param format
     * @return
     * @Description: 将日期转格式化成指定的格式
     * @author liudy1
     * @date 2020年1月16日 下午20:55:19
     */
    public static String formatDate(Date date, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    /**
     * @param date
     * @return
     * @throws ParseException
     * @Description: 将日期转化为日期23：59：59
     * @author yanzl
     * @date 2020年1月16日 下午20:55:19
     */
    public static Date ToDetailTime(Date date) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        date = dateFormat.parse(dateFormat.format(date) + " 23:59:59");
        return date;
    }

    /**
     * @param date
     * @return
     * @Description: 月初第一天
     * @author changjb
     * @date 2020年4月08日 下午20:55:19
     */
    public static Date firstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()) + " 00:00:00");
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return retDate;
    }

    /**
     * @param date
     * @return
     * @Description: 次月第一天
     * @author changjb
     * @date 2020年4月15日 08:35:19
     */
    public static Date firstDayOfNextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()) + " 00:00:00");
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return retDate;
    }

    /**
     * @param date
     * @return
     * @Description: 月末一天
     * @author changjb
     * @date 2020年4月08日 下午20:55:19
     */
    public static Date lastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date retDate = null;
        try {
            retDate = dateFormat.parse(dateFormat.format(calendar.getTime()) + " 00:00:00");
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return retDate;
    }

    /**
     * @param
     * @return
     * @Description: 获得系统当前时间
     * @author changjb
     * @date 2020年4月15日 07:55:19
     */
    public static Date curSysDate() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = df.format(new Date());
        Date date = parseDateTime(s);
        return date;
    }

    public static Date curTodayDate() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String s = df.format(curSysDate());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = dateFormat.parse(s);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return date;
    }

    /**
     * 返回当月最后一天的日期字符串string
     */
    public static String getLastDayOfMonth(String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 返回当月最后一天的日期时间date
     */
    public static Date getLastDayDateOfMonth(String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = dateFormat.parse(dateFormat.format(calendar.getTime()));
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return date;
    }

    /**
     * 只比较时间的年月
     * 获取年月时间，保证输入时间只能在当前系统时间月份中，无法跨月
     * （不能跨月倒追）
     * 场景限制情况：因为这块有和另外的系统要有核算账目之类的系统，涉及到和时间相关的
     * 所以一般暂时不让跨月，在系统里很多地方都不允许跨月
     *
     * @param date
     * @return
     */
    public static Date getYearMonth(Date date) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
        String s = df.format(date);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
        Date resultDate = null;
        try {
            resultDate = dateFormat.parse(s);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
        }
        return resultDate;
    }


    /**
     * 计算2个日期之间相差的  相差多少年月日
     * 比如：2011-02-02 到  2017-03-02 相差 6年，1个月，0天
     *
     * @param fromDate
     * @param toDate
     * @param type     返回值类型   1为多少年，2为多少个月，3为多少天
     * @return
     */
    public static Integer dateCompare(Date fromDate, Date toDate, int type) {
        Calendar from = Calendar.getInstance();
        from.setTime(fromDate);
        Calendar to = Calendar.getInstance();
        to.setTime(toDate);
        //只要年月
        int fromYear = from.get(Calendar.YEAR);
        int fromMonth = from.get(Calendar.MONTH);
        int toYear = to.get(Calendar.YEAR);
        int toMonth = to.get(Calendar.MONTH);
        int year = toYear - fromYear;
        int month = toYear * 12 + toMonth - (fromYear * 12 + fromMonth);
        int day = (int) ((to.getTimeInMillis() - from.getTimeInMillis()) / (24 * 3600 * 1000));
        if (type == 1) {
            return year;
        }
        if (type == 2) {
            return month;
        }
        if (type == 3) {
            return day;
        }
        return null;
    }

    /**
     * 根据出生日期算年龄
     *
     * @param birthDay
     * @return
     * @throws ParseException
     */
    public static int getAgeByBirth(Date birthDay) throws ParseException {
        int age = 0;
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException("生日期晚于当前时间，无法计算!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) age--;//当前日期在生日之前，年龄减一
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }

    /**
     * 得到下周周一
     *
     * @return yyyy-MM-dd
     */
    public static String getMondayOfNextWeek() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 1 + 7);
        //System.out.println(c.getTime());
        return format.format(c.getTime());
    }

    /**
     * 得到本周周四
     *
     * @return yyyy-MM-dd
     */
    public static String getThursdayOfThisWeek() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 4);

        return format.format(c.getTime());
    }

    /**
     * 得到本周周五
     *
     * @return yyyy-MM-dd
     */
    public static String getFridayOfThisWeek() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 5);

        return format.format(c.getTime());
    }

    /**
     * 得到下周周五
     *
     * @return yyyy-MM-dd
     */
    public static String getFridayOfNextWeek() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 5 + 7);
        return format.format(c.getTime());
    }

    /**
     * 得到本周周日
     *
     * @return yyyy-MM-dd
     */
    public static String getSundayOfThisWeek() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 7);
        return format.format(c.getTime());
    }

    /**
     * 获取年
     *
     * @return 年
     */
    public static Integer getYear(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取月
     *
     * @return 月
     */
    public static Integer getMonth(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        /*因为月份是从0开始，所以要+1*/
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取日
     *
     * @return 日
     */
    public static Integer getDay(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取小时
     *
     * @return 小时
     */
    public static Integer getHour(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取分钟
     *
     * @return 分钟
     */
    public static Integer getMinute(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 获取秒
     *
     * @return 秒
     */
    public static Integer getSecond(Date sourceDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(sourceDate);
        return calendar.get(Calendar.SECOND);
    }

    /**
     * 日期添加到分钟得到新时间
     *
     * @param day 开始时间
     * @param x   相隔分钟数
     * @return
     */
    public static Date addDateMinute(String day, int x) {
        //入参的格式
        // 24小时制
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = format.parse(day);
        } catch (Exception ex) {
           throw new RuntimeException(ex);
        }
        if (date == null) {
            return null;
        }
        System.out.println("front:" + format.format(date));
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 24小时制
        cal.add(Calendar.MINUTE, x);
        //得到结算后的结果 yyyy-MM-dd HH:mm
        date = cal.getTime();
        System.out.println("after:" + format.format(date));
        cal = null;
        return date;
    }

}
